-------------------------------------------------------------------------------
--
-- VGA Controller
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity vga_controller is
  
  port (
    reset 		: in std_logic;
    clk   		: in std_logic;                    -- Should be 25.125 MHz
    read       	: in  std_logic;
    write      	: in  std_logic;
    chipselect 	: in  std_logic;
    address    	: in  unsigned(7 downto 0);
    readdata   	: out unsigned(31 downto 0);
    writedata  	: in  unsigned(31 downto 0);
	
    VGA_CLK,                         -- Clock
    VGA_HS,                          -- H_SYNC
    VGA_VS,                          -- V_SYNC
    VGA_BLANK,                       -- BLANK
    VGA_SYNC 	: out std_logic;        -- SYNC
    VGA_R,                           -- Red[9:0]
    VGA_G,                           -- Green[9:0]
    VGA_B 		: out std_logic_vector (9 downto 0); -- Blue[9:0]

	--  Sram interface:
	SRAM_DQ   			 : inout std_logic_vector(15 downto 0);
	SRAM_ADDR            : out std_logic_vector(17 downto 0);
	SRAM_UB_N, SRAM_LB_N : out std_logic;
	SRAM_WE_N, SRAM_CE_N : out std_logic;
	SRAM_OE_N            : out std_logic
    );

end vga_controller;

architecture rtl of vga_controller is

  -- video constants
	constant HTOTAL       			: integer := 800;
	constant HSYNC        			: integer := 96;
	constant HBACK_PORCH  			: integer := 48;
	constant HACTIVE      			: integer := 640;
	constant HFRONT_PORCH 			: integer := 16;
	constant HACTIVE_CNT			: integer := HSYNC + HBACK_PORCH;
  
	constant VTOTAL       			: integer := 525;
	constant VSYNC        			: integer := 2;
	constant VBACK_PORCH  			: integer := 33;
	constant VACTIVE      			: integer := 480;
	constant VFRONT_PORCH 			: integer := 10;
	constant VACTIVE_CNT			: integer := VSYNC + VBACK_PORCH;

	-- sprite constants
	constant N_SPRITE_ANIMATION		:	integer	:= 16;
	constant N_SPRITE_CURSOR		:	integer := 1;
	constant N_SPRITE_TOTAL			: integer := N_SPRITE_ANIMATION + N_SPRITE_CURSOR;
	constant SPRITE_ANIMATION_WIDTH	: integer := 128;
	constant SPRITE_ANIMATION_HEIGHT: integer := 64;
	constant SPRITE_CURSOR_WIDTH	: integer := 9;
	constant SPRITE_CURSOR_HEIGHT	: integer := 11;
	
	-- screen constants
	constant MARGIN_LEFTMOST		: integer := 0;
	constant MARGIN_RIGHTMOST		: integer := 0;
	constant MARGIN_UPPEREND		: integer := 0;
	constant MARGIN_LOWEREND		: integer := 0;
	
	-- color constants
	constant COLOR_BIT_ALPHA		: integer := 15;
	constant COLOR_R_START			: integer := 10;
	constant COLOR_R_END			: integer := 14;
	constant COLOR_G_START			: integer := 5;
	constant COLOR_G_END			: integer := 9;
	constant COLOR_B_START			: integer := 0;
	constant COLOR_B_END			: integer := 4;
	
	-- color data
	signal color_out				: unsigned( 15 downto 0 ) := X"0000";
	
	-- cursor sprite
	signal is_cursor_drawing 		: std_logic := '0';
	signal cursor_pos_x				: unsigned( 9 downto 0 ) := "0001000000";		-- 0 ~ 640
	signal cursor_pos_y				: unsigned( 9 downto 0 ) := "0011000000";		-- 0 ~ 480

	-- animation sprite
	type TYPE_FLAG_ANIMATION_SPRITE is array( 0 to ( N_SPRITE_ANIMATION - 1 ) ) of std_logic;
	signal is_animation_sprite_drawing : TYPE_FLAG_ANIMATION_SPRITE := ( others => '0' );
	type TYPE_H_COLOR_ANIMATION_SPRITE is array( 0 to ( SPRITE_ANIMATION_WIDTH - 1 ) ) of unsigned( 15 downto 0 );
	signal animation_sprite_0_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_1_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_2_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_3_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_4_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_5_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_6_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_7_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_8_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_9_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_10_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_11_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_12_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_13_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_14_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	signal animation_sprite_15_h_color : TYPE_H_COLOR_ANIMATION_SPRITE := ( others => X"0000" );
	
	type TYPE_H_POSITION is array( 0 to ( N_SPRITE_ANIMATION - 1 ) ) of unsigned( 9 downto 0 );
	signal sprite_pos_x : TYPE_H_POSITION := ( others => "0000000000" );
	
	type TYPE_V_POSITION is array( 0 to ( N_SPRITE_ANIMATION - 1 ) ) of unsigned( 9 downto 0 );
	signal sprite_pos_y : TYPE_V_POSITION := ( others => "0000000000" );
	
	---------------------------------------------------------------------------------------------
	
  type HStartMatrix is array (0 to 3) of unsigned(9 downto 0); 
  signal Card_HStart : HStartMatrix := ("0000000000","0010101010","0101010100","0111111110");
  type VStartMatrix is array (0 to 3) of unsigned(9 downto 0); 
  signal Card_VStart : VStartMatrix := ("0000000000","0001010100","0010101000","0011111100");

  -- Signals for the video controller
  signal Hcount : unsigned(9 downto 0);  -- Horizontal position (0-800)
  signal Vcount : unsigned(9 downto 0);  -- Vertical position (0-524) 
  signal EndOfLine, EndOfField : std_logic;
  signal vga_hblank, vga_hsync, vga_vblank, vga_vsync : std_logic;  -- Sync. signals

  signal pic0 : std_logic := '0'; signal pic1 : std_logic := '0'; signal pic2 : std_logic := '0'; signal pic3 : std_logic := '0';
  signal pic4 : std_logic := '0'; signal pic5 : std_logic := '0'; signal pic6 : std_logic := '0'; signal pic7 : std_logic := '0';
  signal pic8 : std_logic := '0'; signal pic9 : std_logic := '0'; signal pic10 : std_logic := '0'; signal pic11 : std_logic := '0';
  signal pic12 : std_logic := '0'; signal pic13 : std_logic := '0'; signal pic14 : std_logic := '0'; signal pic15 : std_logic := '0';

  signal clk_25 : std_logic := '0';

  signal H0Boundary : unsigned(0 to 127) := (others=>'0'); signal H1Boundary : unsigned(0 to 127) := (others=>'0');signal H2Boundary : unsigned(0 to 127) := (others=>'0');signal H3Boundary : unsigned(0 to 127) := (others=>'0');
  signal H4Boundary : unsigned(0 to 127) := (others=>'0');signal H5Boundary : unsigned(0 to 127) := (others=>'0');signal H6Boundary : unsigned(0 to 127) := (others=>'0');signal H7Boundary : unsigned(0 to 127) := (others=>'0'); 
  signal H8Boundary : unsigned(0 to 127) := (others=>'0');signal H9Boundary : unsigned(0 to 127) := (others=>'0');signal H10Boundary : unsigned(0 to 127) := (others=>'0');signal H11Boundary : unsigned(0 to 127) := (others=>'0');
  signal H12Boundary : unsigned(0 to 127) := (others=>'0');signal H13Boundary : unsigned(0 to 127) := (others=>'0');signal H14Boundary : unsigned(0 to 127) := (others=>'0');signal H15Boundary : unsigned(0 to 127) := (others=>'0'); 
  
  signal H0Index : unsigned(9 downto 0);signal H1Index : unsigned(9 downto 0);signal H2Index : unsigned(9 downto 0);signal H3Index : unsigned(9 downto 0); 
  signal H4Index : unsigned(9 downto 0);signal H5Index : unsigned(9 downto 0);signal H6Index : unsigned(9 downto 0);signal H7Index : unsigned(9 downto 0);
  signal H8Index : unsigned(9 downto 0);signal H9Index : unsigned(9 downto 0);signal H10Index : unsigned(9 downto 0);signal H11Index : unsigned(9 downto 0); 
  signal H12Index : unsigned(9 downto 0);signal H13Index : unsigned(9 downto 0);signal H14Index : unsigned(9 downto 0);signal H15Index : unsigned(9 downto 0);
  
  signal V0Index : unsigned(9 downto 0);signal V1Index : unsigned(9 downto 0);signal V2Index : unsigned(9 downto 0);signal V3Index : unsigned(9 downto 0);
  signal V4Index : unsigned(9 downto 0);signal V5Index : unsigned(9 downto 0);signal V6Index : unsigned(9 downto 0);signal V7Index : unsigned(9 downto 0);
  signal V8Index : unsigned(9 downto 0);signal V9Index : unsigned(9 downto 0);signal V10Index : unsigned(9 downto 0);signal V11Index : unsigned(9 downto 0);
  signal V12Index : unsigned(9 downto 0);signal V13Index : unsigned(9 downto 0);signal V14Index : unsigned(9 downto 0);signal V15Index : unsigned(9 downto 0);
  
  type CardMatrix is array (0 to 63) of unsigned (0 to 127);
  signal CardSprite : CardMatrix :=   (	"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
										"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
									);
										
begin
-- Halving the clock that is fed to this component since VGA supports 25Mhz instead of 50Mhz  
  process (clk)
  begin
    if rising_edge(clk) then
      clk_25 <= not clk_25;
    end if;
  end process;

-- Getting the X and Y positions from Nios2 and writing those coordinates into 2 predefined registers
-- namely cursor_pos_x and cursor_pos_y. Where Assuming the first 10 bits have cursor_pos_X data and 
-- the second 10 bits are holding cursor_pos_Y data
  GetCursorPos : process (clk)
  begin
	if rising_edge(clk) then
		if chipselect = '1' then
			if write = '1' then
				if address = X"00" then
					cursor_pos_x <= writedata(9 downto 0);
					cursor_pos_y <= writedata(19 downto 10);
				end if;
			end if;
 		end if;
	end if;
  end process GetCursorPos;

  -- Horizontal and vertical counters
  HCounter : process (clk_25)
  begin
    if rising_edge(clk_25) then      
      if reset = '1' then
        Hcount <= (others => '0');
      elsif EndOfLine = '1' then
        Hcount <= (others => '0');
      else
        Hcount <= Hcount + 1;
      end if;      
    end if;
  end process HCounter;

  EndOfLine <= '1' when Hcount = HTOTAL - 1 else '0';
  
  VCounter: process (clk_25)
  begin
    if rising_edge(clk_25) then      
      if reset = '1' then
        Vcount <= (others => '0');
      elsif EndOfLine = '1' then
        if EndOfField = '1' then
          Vcount <= (others => '0');
        else
          Vcount <= Vcount + 1;
        end if;
      end if;
    end if;
  end process VCounter;

  EndOfField <= '1' when Vcount = VTOTAL - 1 else '0';

  -- State machines to generate HSYNC, VSYNC, HBLANK, and VBLANK

  HSyncGen : process (clk_25)
  begin
    if rising_edge(clk_25) then     
      if reset = '1' or EndOfLine = '1' then
        vga_hsync <= '1';
      elsif Hcount = HSYNC - 1 then
        vga_hsync <= '0';
      end if;
    end if;
  end process HSyncGen;
  
  HBlankGen : process (clk_25)
  begin
    if rising_edge(clk_25) then
      if reset = '1' then
        vga_hblank <= '1';
      elsif Hcount = HSYNC + HBACK_PORCH then
        vga_hblank <= '0';
      elsif Hcount = HSYNC + HBACK_PORCH + HACTIVE then
        vga_hblank <= '1';
      end if;      
    end if;
  end process HBlankGen;

  VSyncGen : process (clk_25)
  begin
    if rising_edge(clk_25) then
      if reset = '1' then
        vga_vsync <= '1';
      elsif EndOfLine ='1' then
        if EndOfField = '1' then
          vga_vsync <= '1';
        elsif Vcount = VSYNC - 1 then
          vga_vsync <= '0';
        end if;
      end if;      
    end if;
  end process VSyncGen;

  VBlankGen : process (clk_25)
  begin
    if rising_edge(clk_25) then    
      if reset = '1' then
        vga_vblank <= '1';
      elsif EndOfLine = '1' then
        if Vcount = VSYNC + VBACK_PORCH - 1 then
          vga_vblank <= '0';
        elsif Vcount = VSYNC + VBACK_PORCH + VACTIVE - 1 then
          vga_vblank <= '1';
        end if;
      end if;
    end if;
  end process VBlankGen;

	-- Cursor Sprite Generation
	CursorGen : process (clk_25)
	type TYPE_CURSOR_H_COLOR is array( 0 to ( SPRITE_CURSOR_WIDTH - 1 ) ) of unsigned( 15 downto 0 );
	variable cursor_h_color_0 : TYPE_CURSOR_H_COLOR := ( others => X"FFFF" );
	variable cursor_h_color_1 : TYPE_CURSOR_H_COLOR := ( others => X"0000" );
	variable cursor_h_color_2 : TYPE_CURSOR_H_COLOR := ( others => X"8000" );
	variable cursor_h_color_3 : TYPE_CURSOR_H_COLOR := ( others => X"0000" );
	variable cursor_h_color_4 : TYPE_CURSOR_H_COLOR := ( others => X"8000" );
	variable cursor_h_color_5 : TYPE_CURSOR_H_COLOR := ( others => X"8000" );
	variable cursor_h_color_6 : TYPE_CURSOR_H_COLOR := ( others => X"FFFF" );
	variable cursor_h_color_7 : TYPE_CURSOR_H_COLOR := ( others => X"FFFF" );
	variable cursor_h_color_8 : TYPE_CURSOR_H_COLOR := ( others => X"FFFF" );
	variable cursor_h_color_9 : TYPE_CURSOR_H_COLOR := ( others => X"0000" );
	variable cursor_h_color_10 : TYPE_CURSOR_H_COLOR := ( others => X"0000" );
	
	variable cursor_h_color_cur : TYPE_CURSOR_H_COLOR := ( others => X"0000" );
	variable cursor_pixel_color_cur : unsigned( 15 downto 0 ) := X"0000";
	
	begin
	if rising_edge(clk_25) then
		if reset = '1' then
				is_cursor_drawing <= '0';
		-- check whether the current horizontal pixel is pointing cursor area
		elsif ( HACTIVE_CNT + cursor_pos_x - 1 < Hcount and Hcount < HACTIVE_CNT + cursor_pos_x + SPRITE_CURSOR_WIDTH ) and
				( VACTIVE_CNT + cursor_pos_y - 1 < Vcount and Vcount < VACTIVE_CNT + cursor_pos_y + SPRITE_CURSOR_HEIGHT ) then

			-- get current cursor line
			case( to_integer( Vcount - VACTIVE_CNT - cursor_pos_y ) ) is
				when 0 => cursor_h_color_cur := cursor_h_color_0;
				when 1 => cursor_h_color_cur := cursor_h_color_1;
				when 2 => cursor_h_color_cur := cursor_h_color_2;
				when 3 => cursor_h_color_cur := cursor_h_color_3;
				when 4 => cursor_h_color_cur := cursor_h_color_4;
				when 5 => cursor_h_color_cur := cursor_h_color_5;
				when 6 => cursor_h_color_cur := cursor_h_color_6;
				when 7 => cursor_h_color_cur := cursor_h_color_7;
				when 8 => cursor_h_color_cur := cursor_h_color_8;
				when 9 => cursor_h_color_cur := cursor_h_color_9;
				when 10 => cursor_h_color_cur := cursor_h_color_10;
				when others => cursor_h_color_cur := ( others => X"0000" );
			end case;
			
			-- get current pixel
			cursor_pixel_color_cur := cursor_h_color_cur( to_integer( Hcount - HACTIVE_CNT - cursor_pos_x ) );
			
			-- set alpha value and color
			is_cursor_drawing <= cursor_pixel_color_cur( COLOR_BIT_ALPHA );
			color_out <= cursor_pixel_color_cur;
		else
			is_cursor_drawing <= '0';
		end if;     
	end if;
  end process CursorGen;


  -- Picture0 Sprite
  Pic0Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic0 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(0) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(0) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(0) + 64 then
		H0Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(0);
		V0Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(0);
		H0Boundary <= CardSprite(TO_INTEGER(V0Index));
			if H0Boundary(TO_INTEGER(H0Index)) = '1' then
				pic0 <= '1';
			elsif H0Boundary(TO_INTEGER(H0Index)) = '0' then
				pic0 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
		pic0 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
	    pic0 <= '0';
    end if;     
    end if;
  end process Pic0Gen;

  -- Picture1 Sprite
  Pic1Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic1 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(0) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(1) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(0) + 64 then
		H1Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(1);
		V1Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(0);
		H1Boundary <= CardSprite(TO_INTEGER(V1Index));
			if H1Boundary(TO_INTEGER(H1Index)) = '1' then
				pic1 <= '1';
			elsif H1Boundary(TO_INTEGER(H1Index)) = '0' then
				pic1 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
		pic1 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
	    pic1 <= '0';
    end if;     
    end if;
  end process Pic1Gen;

  -- Picture2 Sprite
  Pic2Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic2 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(0) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(2) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(0) + 64 then
		H2Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(2);
		V2Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(0);
		H2Boundary <= CardSprite(TO_INTEGER(V2Index));
			if H2Boundary(TO_INTEGER(H2Index)) = '1' then
				pic2 <= '1';
			elsif H2Boundary(TO_INTEGER(H2Index)) = '0' then
				pic2 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
		pic2 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
	    pic2 <= '0';
    end if;     
    end if;
  end process Pic2Gen;

-- Picture3 Sprite
  Pic3Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic3 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(0) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(3) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(0) + 64 then
		H3Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(3);
		V3Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(0);
		H3Boundary <= CardSprite(TO_INTEGER(V3Index));
			if H3Boundary(TO_INTEGER(H3Index)) = '1' then
				pic3 <= '1';
			elsif H3Boundary(TO_INTEGER(H3Index)) = '0' then
				pic3 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
		pic3 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
	    pic3 <= '0';
    end if;     
    end if;
  end process Pic3Gen;

  -- Picture4 Sprite
  Pic4Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic4 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(1) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(0) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(1) + 64 then
		H4Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(0);
		V4Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(0);
		H4Boundary <= CardSprite(TO_INTEGER(V4Index));
			if H4Boundary(TO_INTEGER(H4Index)) = '1' then
				pic4 <= '1';
			elsif H4Boundary(TO_INTEGER(H4Index)) = '0' then
				pic4 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
		pic4 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
	    pic4 <= '0';
    end if;     
    end if;
  end process Pic4Gen;

  -- Picture5 Sprite
  Pic5Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic5 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(1) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(1) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(1) + 64 then
		H5Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(1);
		V5Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(1);
		H5Boundary <= CardSprite(TO_INTEGER(V5Index));
			if H5Boundary(TO_INTEGER(H5Index)) = '1' then
				pic5 <= '1';
			elsif H5Boundary(TO_INTEGER(H5Index)) = '0' then
				pic5 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
		pic5 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
	    pic5 <= '0';
    end if;     
    end if;
  end process Pic5Gen;

  -- Picture6 Sprite
  Pic6Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic6 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(1) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(2) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(1) + 64 then
		H6Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(2);
		V6Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(1);
		H6Boundary <= CardSprite(TO_INTEGER(V6Index));
			if H6Boundary(TO_INTEGER(H6Index)) = '1' then
				pic6 <= '1';
			elsif H6Boundary(TO_INTEGER(H6Index)) = '0' then
				pic6 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
		pic6 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
	    pic6 <= '0';
    end if;     
    end if;
  end process Pic6Gen;

-- Picture7 Sprite
  Pic7Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic7 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(1) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(3) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(1) + 64 then
		H7Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(3);
		V7Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(1);
		H7Boundary <= CardSprite(TO_INTEGER(V3Index));
			if H7Boundary(TO_INTEGER(H7Index)) = '1' then
				pic7 <= '1';
			elsif H7Boundary(TO_INTEGER(H7Index)) = '0' then
				pic7 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
		pic7 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
	    pic7 <= '0';
    end if;     
    end if;
  end process Pic7Gen;

  -- Picture8 Sprite
  Pic8Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic8 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(2) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(0) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(2) + 64 then
		H8Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(0);
		V8Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(2);
		H8Boundary <= CardSprite(TO_INTEGER(V8Index));
			if H8Boundary(TO_INTEGER(H8Index)) = '1' then
				pic8 <= '1';
			elsif H8Boundary(TO_INTEGER(H8Index)) = '0' then
				pic8 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
		pic8 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
	    pic8 <= '0';
    end if;     
    end if;
  end process Pic8Gen;

  -- Picture9 Sprite
  Pic9Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic9 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(2) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(1) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(2) + 64 then
		H9Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(1);
		V9Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(2);
		H9Boundary <= CardSprite(TO_INTEGER(V9Index));
			if H9Boundary(TO_INTEGER(H9Index)) = '1' then
				pic9 <= '1';
			elsif H9Boundary(TO_INTEGER(H9Index)) = '0' then
				pic9 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
		pic9 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
	    pic9 <= '0';
    end if;     
    end if;
  end process Pic9Gen;

  -- Picture10 Sprite
  Pic10Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic10 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(2) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(2) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(2) + 64 then
		H10Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(2);
		V10Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(2);
		H10Boundary <= CardSprite(TO_INTEGER(V10Index));
			if H10Boundary(TO_INTEGER(H10Index)) = '1' then
				pic10 <= '1';
			elsif H10Boundary(TO_INTEGER(H10Index)) = '0' then
				pic10 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
		pic10 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
	    pic10 <= '0';
    end if;     
    end if;
  end process Pic10Gen;

-- Picture11 Sprite
  Pic11Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic11 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(2) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(3) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(2) + 64 then
		H11Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(3);
		V11Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(2);
		H11Boundary <= CardSprite(TO_INTEGER(V11Index));
			if H11Boundary(TO_INTEGER(H11Index)) = '1' then
				pic11 <= '1';
			elsif H11Boundary(TO_INTEGER(H11Index)) = '0' then
				pic11 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
		pic11 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
	    pic11 <= '0';
    end if;     
    end if;
  end process Pic11Gen;

  -- Picture12 Sprite
  Pic12Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic12 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(3) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(0) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(3) + 64 then
		H12Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(0);
		V12Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(3);
		H12Boundary <= CardSprite(TO_INTEGER(V12Index));
			if H12Boundary(TO_INTEGER(H12Index)) = '1' then
				pic12 <= '1';
			elsif H12Boundary(TO_INTEGER(H12Index)) = '0' then
				pic12 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
		pic12 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(0) + 127 then
	    pic12 <= '0';
    end if;     
    end if;
  end process Pic12Gen;

  -- Picture13 Sprite
  Pic13Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic13 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(3) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(1) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(3) + 64 then
		H13Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(1);
		V13Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(3);
		H13Boundary <= CardSprite(TO_INTEGER(V13Index));
			if H13Boundary(TO_INTEGER(H13Index)) = '1' then
				pic13 <= '1';
			elsif H13Boundary(TO_INTEGER(H13Index)) = '0' then
				pic13 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
		pic13 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(1) + 127 then
	    pic13 <= '0';
    end if;     
    end if;
  end process Pic13Gen;

  -- Picture14 Sprite
  Pic14Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic14 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(3) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(2) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(3) + 64 then
		H14Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(2);
		V14Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(3);
		H14Boundary <= CardSprite(TO_INTEGER(V14Index));
			if H6Boundary(TO_INTEGER(H14Index)) = '1' then
				pic14 <= '1';
			elsif H14Boundary(TO_INTEGER(H14Index)) = '0' then
				pic14 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
		pic14 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(2) + 127 then
	    pic14 <= '0';
    end if;     
    end if;
  end process Pic14Gen;

-- Picture15 Sprite
  Pic15Gen : process (clk_25)
  begin
    if rising_edge(clk_25) then  
	if reset = '1' then   
	  pic15 <= '0';
    elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) - 1 and Vcount > VSYNC + VBACK_PORCH + Card_VStart(3) - 1 then
      if Hcount < HSYNC + HBACK_PORCH + Card_HStart(3) + 128 and Vcount < VSYNC + VBACK_PORCH + Card_VStart(3) + 64 then
		H15Index <= Hcount - HSYNC - HBACK_PORCH - Card_HStart(3);
		V15Index <= Vcount - VSYNC - VBACK_PORCH - Card_VStart(3);
		H15Boundary <= CardSprite(TO_INTEGER(V15Index));
			if H15Boundary(TO_INTEGER(H15Index)) = '1' then
				pic15 <= '1';
			elsif H15Boundary(TO_INTEGER(H15Index)) = '0' then
				pic15 <= '0';
			end if;
      elsif Hcount > HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
		pic15 <= '0';
      end if; 
	elsif Hcount = HSYNC + HBACK_PORCH + Card_HStart(3) + 127 then
	    pic15 <= '0';
    end if;     
    end if;
  end process Pic15Gen;

  -- Registered video signals going to the video DAC
  VideoOut: process (clk_25, reset)
	-- variables for transferring from color_out to VGA_R,G,B
	variable color_r : unsigned( 9 downto 0 ) := "0000000000";
	variable color_g : unsigned( 9 downto 0 ) := "0000000000";
	variable color_b : unsigned( 9 downto 0 ) := "0000000000";
  begin
		-- split 15-bit color data into 5-bit R, G, B data
	color_r( 9 downto 5 ) := color_out( COLOR_R_END downto COLOR_R_START );
	color_g( 9 downto 5 ) := color_out( COLOR_G_END downto COLOR_G_START );
	color_b( 9 downto 5 ) := color_out( COLOR_B_END downto COLOR_B_START );
	
    if reset = '1' then
      VGA_R <= "0000000000";
      VGA_G <= "0000000000";
      VGA_B <= "0000000000";
    elsif clk_25'event and clk_25 = '1' then
	  if is_cursor_drawing = '1' then
		VGA_R <= std_logic_vector( color_r );
        VGA_G <= std_logic_vector( color_g );
        VGA_B <= std_logic_vector( color_b );
      elsif pic0 = '1' or pic2 = '1' or pic5 = '1' or pic7 = '1' or pic8 = '1' or pic10 = '1' or pic13 = '1' or pic15 = '1' then
        VGA_R <= "1111101111";
        VGA_G <= "0111001111";
        VGA_B <= "0111110011";
      elsif pic1 = '1' or pic3 = '1' or pic4 = '1' or pic6 = '1' or pic9 = '1' or pic11 = '1' or pic12 = '1' or pic14 = '1' then
		VGA_R <= "0111001111";
        VGA_G <= "0111001111";
        VGA_B <= "1111110011";
      elsif vga_hblank = '0' and vga_vblank ='0' then
        VGA_R <= "0000000000";
        VGA_G <= "0000000000";
        VGA_B <= "0000000000";
      else
        VGA_R <= "0000000000";
        VGA_G <= "0000000000";
        VGA_B <= "0000000000";    
      end if;
    end if;

--	if EndOfField = '1' then
--		readdata(0)<='1';
--    else
--		readdata(0)<='0';
--    end if;
  end process VideoOut;

  VGA_CLK <= clk_25;
  VGA_HS <= not vga_hsync;
  VGA_VS <= not vga_vsync;
  VGA_SYNC <= '0';
  VGA_BLANK <= not (vga_hsync or vga_vsync);
end rtl;
